# -*- coding: utf-8 -*-
from django.db.models import permalink, signals
from google.appengine.ext import db
from ragendja.dbutils import cleanup_relations
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from attachments.models import Attachment

import datetime
import debt

key_TitleConfig="TitleConfig"
def create_TitleConfig():
    ctx=TitleConfig(key_name=key_TitleConfig)
    #ctx.put()
    debt.save_obj(ctx,key_TitleConfig)
    return ctx
    
class TitleConfig(db.Model):
    """
    System configuration class
    """
    LBFORUM_TITLE       =   db.StringProperty(default='Word Talk')
    LBFORUM_SUB_TITLE   =   db.StringProperty(default="""Also A Clone of LBForum.""")
    #Friendly_Link      =   db.StringListProperty(default=["<a href='http://word-talk.appspot.com' title='Word Talk BBS'>Word Talk BBS</a>"])
    cache_time_out  = 60
    def to_cfg(self):
        return {
        'LBFORUM_TITLE': self.LBFORUM_TITLE,
        'LBFORUM_SUB_TITLE': self.LBFORUM_SUB_TITLE,
        }
    def __unicode__(self):
        return self.LBFORUM_TITLE

class FriendLink(db.Model):
     name   =   db.StringProperty(default='Word Talk BBS ')
     url   =   db.StringProperty(default='http://word-talk.appspot.com')
     title  =   db.StringProperty(default='Word Talk BBS')
     
     def __str__(self):
         return self.title
     
class Category(db.Model):
    name = db.StringProperty(default="Category")
    description = db.TextProperty(default = '')
    ordering = db.IntegerProperty(default = 1)    
    created_on = db.DateTimeProperty(auto_now_add = True)
    updated_on = db.DateTimeProperty()
    
    def __unicode__(self):
        return self.name
    """
    def forum_set(self):
        q_forum=Forum.all().filter('category = ', self)
        return q_forum.get()
    """    

class Forum(db.Model):
    name = db.StringProperty()
    #slug = models.SlugField(max_length = 110)#unic...
    #slug=db.URLProperty()
    slug=db.StringProperty()
    description = db.TextProperty(default='')
    ordering = db.IntegerProperty(default = 1)
    category = db.ReferenceProperty(Category)
    created_on = db.DateTimeProperty(auto_now_add = True)
    updated_on = db.DateTimeProperty()
    num_topics = db.IntegerProperty(default = 0)
    num_posts = db.IntegerProperty(default = 0)

    #last_post = db.ReferenceProperty(Post)#db.IntegerProperty()#pickle obj
    #last_post =db.StringProperty()
    last_post_key=db.StringProperty()
    #DoesNotExist ="yes"
    fid = db.IntegerProperty(default=0)
    
    class Meta:
        verbose_name = _("Forum")
        verbose_name_plural = _("Forums")
        ordering = ('ordering','-created_on')
    
    def get_cnt(self,type,cnt):
        #now type is Topic
        #return 10
        pass
    def get_topic(self,cnt,date_ts):
        lst_topic=[]
        if date_ts is None:
            try:
                #q_lst_topic=self.topic_set.all().order('- last_reply_on')
                #lst_topics=q_lst_topics.fetch(cnt)
                q_lst_topic=Topic.all()
                q_lst_topic.filter('forum = ',self)
                q_lst_topic.order('-last_reply_on')
                lst_topic=q_lst_topic.fetch(cnt)
            except:
                pass
            return lst_topic 
        else:
            q =Topic.all()
            q.filter('forum = ',self)
            q=self.topic_set.all()
            date = datetime.datetime.utcfromtimestamp(date_ts)
            q.filter('last_reply_on < ',date)
            q.order('-last_reply_on')
            lst_topic = q.fetch(cnt)
            return lst_topic
        
    def count_nums_topic(self):
        return self.topic_set.all().count()

    def count_nums_post(self):
        return self.topic_set.all().aggregate(Sum('num_replies'))['num_replies__sum']

    def get_last_post(self):
        if not self.last_post_key:
            return None
        
        post= Post.get_by_key_name(self.last_post_key)
        return post
     
        #if not self.last_post:
        #    return {}
        #return pickle.loads(b64decode(self.last_post))
    

    def get_absolute_url(self):
        #return ('lbforum_forum', (), {'forum_slug': self.slug})
        #return ('/lbforum/forum/%s'%self.slug)
        return ('/forum/%s'%self.slug)

    def __unicode__(self):
        return self.name 
    
        
#class TopicManager(models.Manager):    
class TopicManager(db.Model):
    def get_query_set(self):
        return super(TopicManager, self).get_query_set().filter(hidden = False)
    
class Topic(db.Model):
    forum = db.ReferenceProperty(Forum, verbose_name=_('Forum'))
    posted_by = db.ReferenceProperty(User)
    
    subject = db.StringProperty()
    num_views = db.IntegerProperty(default=0)
    num_replies = db.IntegerProperty(default = 0)#posts...
    created_on = db.DateTimeProperty(auto_now_add=True)
    updated_on = db.DateTimeProperty()
    last_reply_on = db.DateTimeProperty(auto_now_add = True)

    #last_post = db.StringProperty()#pickle obj
    #last_post = db.ReferenceProperty(Post)
    last_post_key= db.StringProperty()
    
    #Moderation features
    closed = db.BooleanProperty(default=False)
    sticky = db.BooleanProperty(default=False)
    hidden = db.BooleanProperty(default=False)
    
    objects = TopicManager()
    seq = db.IntegerProperty(default=0)
    
    prefix="t"
    
    def get_cnt(self,type):
        return self.num_replies+1
    
    class Meta:
        ordering = ('-last_reply_on',)#'-sticky'
        #get_latest_by = ('created_on')
        verbose_name = _("Topic")
        verbose_name_plural = _("Topics")
        
    def __unicode__(self):
        return self.subject

    def count_nums_replies(self):
        return self.post_set.all().count()
    

    def get_absolute_url(self):
        #http://localhost:8080/lbforum/topic/agphZXAtc2FtcGxlchQLEg1sYmZvcnVtX3RvcGljGJ0BDA/
        #return ('lbforum_topic', (), {'topic_id': self.id})
        #return "/lbforum/topic/%s/"%self.id
        #return "/lbforum/topic/%d/"%self.seq
        return "/topic/%d/"%self.seq
    
    def get_last_post(self):
        #if not self.last_post:
        post=None
        if self.last_post_key is not None:
            #return {}
            post = Post.get_by_key_name(self.last_post_key)
        return post
        #return pickle.loads(b64decode(self.last_post))
    

# Create Replies for a topic
class Post(db.Model):#can't edit...
    #topic = models.ForeignKey(Topic, verbose_name=_('Topic'))
    topic = db.ReferenceProperty(Topic)
    posted_by = db.ReferenceProperty(User)
    poster_ip = db.StringProperty() #IP
    topic_post = db.BooleanProperty(default=False)
    
    #TODO add html/rst/..suport
    message = db.TextProperty() #models.TextField()
    attachments = db.ReferenceProperty(Attachment)  #models.ManyToManyField(Attachment, blank = True)
    
    created_on = db.DateTimeProperty(auto_now_add=True) #models.DateTimeField(auto_now_add=True)
    updated_on = db.DateTimeProperty()  #models.DateTimeField(blank = True, null = True)
    edited_by = db.StringProperty() #models.CharField(max_length = 255, blank=True)#user name
    
    seq_in_topic = db.IntegerProperty(default=0)
    
    prefix="p"
    cache_time_out=0
    
    class Meta:
        verbose_name = _("Post")
        verbose_name_plural = _("Posts")
        ordering = ('-created_on',)
        #get_latest_by = ('created_on', )
        
    def __unicode__(self):
        return self.message[:80]
    
    def update(self):
        if self.updated_on is None:
            return self.created_on
        else:
            return self.updated_on
        
    def subject(self):
        if self.topic_post:
            return _('Topic: %s') % self.topic.subject
        return _('Re: %s') % self.topic.subject

    def update_attachments(self, attachment_ids):
        if self.attachments is None:
            return
        
        self.attachments.clear()
        for attachment_id in attachment_ids:
            try:
                attachment = Attachment.objects.get(pk=attachment_id)
            except:
                continue
            attachment.activated = True
            attachment.save()
            self.attachments.add(attachment)

    #@models.permalink
    def get_absolute_url(self):
        return ('lbforum_post', (), { 'post_id': self.pk })

    def get_absolute_url_ext(self):
        topic = self.topic
        #post_idx = topic.post_set.filter(created_on__lte=self.created_on).count()
        q_post=topic.post_set
        q_post.filter('created_on < ', self.created_on)
        post_idx=q_post.count()
        #page = (post_idx - 1) / 20 + 1
        page=post_idx  / 20 + 1
        #url_p='%s?page=%s#p%s' % (topic.get_absolute_url(), page, self.pk)
        #return '%s?page=%s#p%s' % (topic.get_absolute_url(), page, self.pk)
        url_p= '?page=%s#p%s' %(str(page),self.pk)
        #return url_p
        #return '%s?page=%s#p%s' % ('/lbforum/topic/'+topic.id, page, self.pk)
        #return '%s?page=%s#p%s' % ('/lbforum/topic/'+str(topic.seq), page, self.id)
        return '%s?page=%s#p%s' % ('/topic/'+str(topic.seq), page, self.id)
        #return "/test"
        

class LBForumUserProfile(db.Model):
    #user = models.OneToOneField(User, related_name='lbforum_profile', verbose_name=_('User'))
    user = db.ReferenceProperty(User)
    #last_activity = models.DateTimeField(auto_now_add=True)
    last_activity = db.DateTimeProperty(auto_now_add=True)
    
    #userrank = models.CharField(max_length=30,default=_("Junior Member"))
    userrank = db.StringProperty(default=_("Junior Member"))
    #last_posttime = models.DateTimeField(auto_now_add=True)
    last_posttime = db.DateTimeProperty (auto_now_add=True)
    
    #signature = models.CharField(max_length = 1000, null = True, blank = True)
    signature = db.StringProperty()
    
    def __unicode__(self):
        return self.user.username
    
    def get_total_posts(self):
        return self.user.post_set.count()

    def get_absolute_url(self):
        return self.user.get_absolute_url()        
"""
    Word Talk BBS
"""

class WTModel(db.Model):
    seq     =db.IntegerProperty(default=1)
    
    def get_keyname(self):
        #product current obj's keyname
        raise "You should implement this method"
    
    @staticmethod 
    def mk_keyname(container_obj,index):
        #make keyname of current TYPE
        raise "You should implement this method"
    
    @staticmethod 
    def get_by_seq(seq):
        raise "You should implement this method"
    #def get_by_keyname(key):
    def save(self):
        self.put()

class WTContainer(WTModel):
    size = db.IntegerProperty(default=1000)
    def get_obj_list_key(self):
        raise  "You should implement this method:"+"get_obj_list_key()"
    
import datetime    
x=datetime.datetime.now()

class Room(WTContainer):
    #only on in bbs
    title=db.StringProperty(default="Board title")
    lst_bc_seq  =   db.StringListProperty()
    def get_obj_list_key(self):
        return "Room_"+str(self.seq)

class BoardGroup(WTContainer):
    title=db.StringProperty(default="BoardGroup")
    lst_board_seq=db.StringListProperty()
    
    def get_obj_list_key(self):
        return "BoardGroup_"+str(self.seq)
    
class Board(WTContainer):
    #seq     =db.IntegerProperty(default=0)
    title    =db.StringProperty(default="Board title")
    desc    =db.StringProperty(default="Board description")
    #master      =db.ListProperty(int,required=True)
    lst_master  =db.StringListProperty()
    thread_cnt  =db.IntegerProperty(default=222)
    last_post_date  =db.DateTimeProperty(default=datetime.datetime.now())
    room_seq    =db.IntegerProperty(default=0)
    
    def get_last_post_date(self):
        return str(self.last_post_date).split(".")[0]
    @staticmethod
    def mk_keyname(container,index):
        room=container
        seq=index
        return "Board@"+str(room.seq)+"_"+str(seq)
    
    @staticmethod 
    def get_by_seq(seq):
        return Board()
    
class Thread(WTContainer):
    #seq =db.IntegerProperty(default=0)
    board_seq=db.IntegerProperty(default=0)
    author_seq  =db.IntegerProperty(default=0)
    
    
    title           =  db.StringProperty(default="邻家有狗")
    created_date    =  db.DateTimeProperty(default=x)
    last_post_date =  db.DateTimeProperty(default=x)
    priority        =  db.IntegerProperty(default=0)
    top_floor       =  db.IntegerProperty(default=0)   
    post_cnt        =db.IntegerProperty(default=1)
    
    def get_last_post_date(self):
        return str(self.last_post_date).split(".")[0]     
    
    def load_page(self,page_no):
        page_no=int(page_no.encode('ascii'))
        page=Page()
        page.load(self.seq, page_no)
        return page

    @staticmethod
    def mk_keyname(board,seq):
        return "Thread@"+str(board.seq)+"_"+str(seq)
    
    @staticmethod
    def get_by_seq(seq):
        board=Thread()
        board.seq=seq
        return board
            
class WT_User(WTModel):
    #seq     =db.IntegerProperty(default=1)
    name    =db.StringProperty(default="tom")
    email_address   =db.EmailProperty(default="aliufei@126.com")
    password   =db.StringProperty(default="123456")
    @staticmethod 
    def get_by_seq(seq):
        return WT_User()





def get_thread_post(thread_seq,post_seq):
    post=Post()
    return post

def get_obj(obj_type,seq):
    obj=obj_type(seq=seq)
    return obj
def get_type_key_name_by_seq(obj_type,seq):
    return str(obj_type)+"_"+"seq"+"_"+seq

class Cell:
    def __init__(self,obj,desc):
        self.obj=obj
        self.desc=desc
    obj=None
    desc=None
    
class LoadByKeyName:
    container_obj=None
    obj_type=None
    start=0
    end=0
    lst_obj=None
    def __init__(self,container_obj,obj_type,start,end):
        self.container_obj=container_obj
        self.obj_type = obj_type
        self.start=start
        self.end=end
        self.lst_obj=[]
        
    def load(self):
        index=self.start
        while index < self.end:
            keyname=self.obj_type.mk_keyname(self.container_obj,index)
            index=index+1
            obj=get_obj_by_keyname(keyname)
            #obj.thread_cnt=index
            if obj is None:
                continue
            self.lst_cell.append(Cell(obj,None))

        
class Page:
    lst_cell=None
    policy_obj=None
    def __init__(self,container_obj,obj_type,current_page_no):
        self.lst_cell=[]
        self.lst_all_page_no=[]
        self.current_page_no=current_page_no
        self.container_obj=container_obj                
    
    max_obj_seq=0
    page_size=100
    current_page_no=1
    lst_all_page_no=None
    container_obj=None
    obj_type=None 
    
    def load_lst_obj(self):
        lst_obj_key_name = self.container_obj
        index=self.page_size*(self.current_page_no-1)
        end=self.page_size*self.current_page_no+1
        while index < end:
            keyname=self.obj_type.mk_keyname(self.container_obj,index)
            index=index+1
            obj=get_obj_by_keyname(keyname)
            #obj.thread_cnt=index
            if obj is None:
                continue
            self.lst_cell.append(Cell(obj,None))
            
            
    def load_lst_all_page_no(self):
        #start = 1
        end =self.container_obj.size
        self.lst_all_page_no=range(1,end/self.page_size+1)
    
    def load(self):
        self.load_lst_all_page_no()
        self.load_lst_obj()
        
    """        
    def load(self,thread_seq,page_no):
        self.page_no=page_no
        #print type(page_no)
        #print page_no
        #page_no=2
        self.lst_post=[]
        start=self.page_size*self.page_no
        start=start+1
        
        end=self.page_size*(self.page_no+1)
        index=start
        while index <=end :
            post=get_thread_post(thread_seq,index)
            self.lst_post.append(post)
            index=index+1
        return self.lst_post
    """
    
class Post2(WTModel):
    #seq=db.IntegerProperty(default=0)
    floor=db.IntegerProperty(default=1)
    author_seq = db.IntegerProperty(default=1)
    post_date=db.DateTimeProperty(default=x)
    content=db.TextProperty(default="this is text")
    thread_seq=db.IntegerProperty(default=0)
    
    # type@containerseq_objkeyfield
    def get_keyname(self):
        return "Post@"+self.thread_seq+"_"+self.floor
    
    @staticmethod 
    def mk_keyname(thread,floor):
        return "Post@"+str(thread.seq)+"_"+str(floor)
    
        
def get_obj_by_keyname(keyname):
    #return Board()
    obj_type=keyname.split("@")[0]
    obj=eval(obj_type+"()")
    #obj.title=obj.title+str(keyname)
    return obj            

class SeqList(WTModel):
    
    #obj_list=db.ListProperty(int)
    obj_list=db.StringListProperty(required=True)
    desc=db.StringProperty(default="no desc")
    


        